package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.abstracts.AbstractCrmAddDataService;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.data.service.CabinetFileService;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.service.ProModelService;
import com.xbongbong.paas.service.dynamic.help.DynamicHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.domain.entity.ReRollBackEntity;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.domain.entity.ContractSubDataEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.workflow.MarketActivityForStaticHelp;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractSubDataModel;
import com.xbongbong.saas.service.ContractService;
import com.xbongbong.saas.service.DingRobotService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 *
 * @author 魏荣杰
 * @date 2021/1/4 15:37
 * @since
 * @version
 */
@Service("contractFormDataServiceImpl")
public class ContractFormDataServiceImpl extends AbstractCrmAddDataService {

    private static final Logger LOG = LoggerFactory.getLogger(ContractFormDataServiceImpl.class);
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private ContractModel contractModel;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private DingRobotService dingRobotService;
    @Resource
    private CabinetFileService cabinetFileService;
    @Resource
    private ContractService contractService;
    @Resource
    private ProModelService proModelService;
    @Resource
    private DynamicHelp dynamicHelp;
    @Resource
    private MarketActivityForStaticHelp marketActivityForStaticHelp;
    @Resource
    private ContractSubDataModel contractSubDataModel;

    @Override
    public List<Integer> businessList() {
        return Arrays.asList(XbbRefTypeEnum.CONTRACT.getCode());
    }
    @Override
    public SaveVO save(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            UserVO userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired();
            if (Objects.equals(1, noApprovalRequired)) {
                JSONObject data = paasFormDataEntity.getData();
                JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(data, ContractEnum.PRODUCT.getAttr());
                data.remove(ContractEnum.ADD_PAYMENT.getAttr());
                data.remove(ContractEnum.ADD_PAYMENT_SHEET.getAttr());
                data.remove(ContractEnum.ADD_WRITE_OFF_PREPAYMENT.getAttr());
                FormDataUtil.removeSystemData(data);
                Object richTextData = removeRichText(data);
                // 添加已出库优惠金额字段以及默认值
                if(!data.containsKey(ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr())){
                    data.put(ContractEnum.OUTSTOCK_DISCOUNT_AMOUNT.getAttr(), 0);
                }
                if(!data.containsKey(ContractEnum.OUTSTOCK_OTHER_EXPENSE.getAttr())){
                    data.put(ContractEnum.OUTSTOCK_OTHER_EXPENSE.getAttr(), 0);
                }
                paasFormDataEntity.setData(data);
                ContractEntityExt contractEntityExt = new ContractEntityExt();
                BeanUtil.copyProperties(paasFormDataEntity, contractEntityExt);
                contractModel.insert(contractEntityExt);
                dataId = contractEntityExt.getId();

                contractEntityExt.getData().put(ContractEnum.PRODUCT.getAttr(),productArray);
                // 设置属性用于返回
                setPartialAttributes(dataId, contractEntityExt.getSubFormData(), contractEntityExt.getData(), contractEntityExt.getAddTime(),
                        contractEntityExt.getUpdateTime(), paasFormDataEntity, beforeSaveVO);
                // 保存合同后的操作
                dataId = contractEntityExt.getId();
                //文件柜数据保存
                saveFile(formDataAddDTO, paasFormDataEntity, userVO);
                //富文本数据保存
                saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);
            }
            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO);
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public void saveRollBack(Long id, String corpid, Integer saasMark, Integer businessType) throws XbbException {
        if (id == null || id == 0 || corpid == null || saasMark == null) {
            return ;
        }
        IndexTypeEnum indexTypeEnum = getIndexTypeEnum(corpid, saasMark, businessType);
        //删除主表es数据
        physicalDeleteFormData(id, corpid, indexTypeEnum);
        // 子表单的删除
        List<ContractSubDataEntity> contractSubDataEntities = contractSubDataModel.getByDataId(id, corpid);
        if (!contractSubDataEntities.isEmpty()) {
            physicalDeleteSubBatch(corpid, contractSubDataEntities, IndexTypeEnum.IDX_SAAS_CONTRACT_SUB);
        }
    }


    @Override
    public FormDataAddVO afterSave(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        ReRollBackEntity reRollBackEntity = new ReRollBackEntity();
        try {
            if (Objects.equals(1, saveVO.getNoApprovalRequired())) {
                SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
                BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
                SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = beforeSaveVO.getSaasNeedRedundantAttrPojo();

                saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(saasNeedRedundantAttrPoJo);
                packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
                contractService.afterSave(saasFormSaveDTO);
                // 新增加入至中间表 fix 直接调com.xbongbong.saas.help.workflow.MarketActivityForStaticHelp.addMarketActivity
                marketActivityForStaticHelp.addMarketActivity(paasFormDataEntity, XbbRefTypeEnum.CONTRACT);
                boolean isImport = Objects.equals(1, formDataAddDTO.getIsImport());
                // 导入不走回款线程保存，为了保证回款数据及时保存
                Runnable runnable = () -> {
                    try {
                        // 保存回款
                        if(!isImport) {
                            proModelService.saveLinkPayment(saasFormSaveDTO, paasFormDataEntity, saasNeedRedundantAttrPoJo);
                            proModelService.saveLinkPaymentSheet(saasFormSaveDTO, paasFormDataEntity, saasNeedRedundantAttrPoJo);
                        } else {
                            proModelService.saveLinkPayment(saasFormSaveDTO, paasFormDataEntity, saasNeedRedundantAttrPoJo);
                            proModelService.saveLinkPaymentSheet(saasFormSaveDTO, paasFormDataEntity, saasNeedRedundantAttrPoJo);
                        }
                    } catch (Exception e) {
                        LOG.error("保存合同时保存回款", e);
                    }
                };
                threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
                // 记录日志
                afterSaveLog(formDataAddDTO, paasFormEntity, paasFormDataEntity, saveVO, beforeSaveVO);
                // 动态处理
                dynamicHelp.addLinkData(saasFormSaveDTO);
                // api
                apiHook(formDataAddDTO, saveVO, beforeSaveVO);
                // 业务规则
                activeRule(formDataAddDTO, beforeSaveVO, paasFormDataEntity, beforeSaveVO.getPaasFormEntityExt());

                String signer = paasFormDataEntity.getData().getString(ContractEnum.SIGN_PERSON.getAttr());
                String signName = paasFormDataEntity.getData().getString(ContractEnum.SIGN_NAME.getAttr());
                Runnable sendRobotRunnable = () -> {
                    try {
                        dingRobotService.sendRobotByBusinessType(corpid, signer, signName, paasFormDataEntity, XbbRefTypeEnum.CONTRACT);
                    } catch (Exception e) {
                        LOG.error("发送群消息出错", e);
                    }
                };
                threadPoolBeanConfig.sendRobotMsgThreadPool().execute(sendRobotRunnable);

                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
                formDataAddVO.setDataId(saveVO.getDataId());
                formDataAddVO.setFormDataId(saveVO.getDataId());
            } else {
                formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_PROCESS_RETURN_MSG));
                formDataAddVO.setCode(PaasConstant.FORM_ADD_PROCESS_RETURN_CODE);
            }

        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            afterSaveRollBack(paasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            afterSaveRollBack(paasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
        return formDataAddVO;
    }


    @Override
    public void apiHook(FormDataAddDTO formDataAddDTO, SaveVO saveVO, BeforeSaveVO beforeSaveVO) throws XbbException {
        lowCodeExecuteService(formDataAddDTO, saveVO, beforeSaveVO);
    }

    @Override
    public SaveVO saveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        try {
            UserVO userVO = getUserName(formDataAddDTO, paasFormDataEntity);
            Integer noApprovalRequired = beforeSaveVO.getNoApprovalRequired();

            JSONObject data = paasFormDataEntity.getData();
            JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(data, ContractEnum.PRODUCT.getAttr());
            Object richTextData = removeRichText(data);
            JSONObject originData = (JSONObject) data.clone();
            FormDataUtil.removeSystemData(data);
            data.remove(ContractEnum.ADD_PAYMENT.getAttr());
            data.remove(ContractEnum.ADD_PAYMENT_SHEET.getAttr());
            data.remove(ContractEnum.ADD_WRITE_OFF_PREPAYMENT.getAttr());
            paasFormDataEntity.setData(data);
            ContractEntityExt contractEntityExt = new ContractEntityExt();
            BeanUtil.copyProperties(paasFormDataEntity, contractEntityExt);
            contractModel.insert(contractEntityExt);
            dataId = contractEntityExt.getId();

            contractEntityExt.getData().put(ContractEnum.PRODUCT.getAttr(),productArray);
            // 设置属性用于返回
            setPartialAttributes(dataId, contractEntityExt.getSubFormData(), contractEntityExt.getData(), contractEntityExt.getAddTime(), contractEntityExt.getUpdateTime(), paasFormDataEntity, beforeSaveVO);
            // 保存合同后的操作
            dataId = contractEntityExt.getId();
            //文件柜数据保存
//            saveFile(formDataAddDTO, paasFormDataEntity, userVO);
            //富文本数据保存
            saveRichText(formDataAddDTO, paasFormDataEntity, richTextData);

            // 把原始的数据保存，传下去
            originData.put(ContractEnum.PRODUCT.getAttr(), productArray);
            paasFormDataEntity.setData(originData);
            return new SaveVO(noApprovalRequired, paasFormDataEntity, dataId, userVO);
        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            saveRollBack(dataId, corpid, saasMark, businessType);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    @Override
    public FormDataAddVO afterSaveForWorkflow(FormDataAddDTO formDataAddDTO, BeforeSaveVO beforeSaveVO, SaveVO saveVO, PaasFormEntityExt paasFormEntity, PaasFormDataEntity paasFormDataEntity) throws XbbException {
        FormDataAddVO formDataAddVO = new FormDataAddVO();
        Long dataId = saveVO.getDataId();
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        ReRollBackEntity reRollBackEntity = new ReRollBackEntity();
        try {
            SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
            BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
            SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo = beforeSaveVO.getSaasNeedRedundantAttrPojo();

            saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(saasNeedRedundantAttrPoJo);
            packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
            contractService.afterSaveForWorkflow(saasFormSaveDTO);

            formDataAddVO.setDataId(saveVO.getDataId());
            formDataAddVO.setFormDataId(saveVO.getDataId());

            formDataAddVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
            formDataAddVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);

        } catch (XbbException e) {
            LOG.warn(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            afterSaveRollBack(paasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
            throw e;
        } catch (Exception e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            afterSaveRollBack(paasFormDataEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
        return formDataAddVO;
    }

    @Override
    public void afterSaveRollBack(PaasFormDataEntity newPaasFormDataEntity, Long dataId, String corpid, Integer saasMark, Integer businessType, ReRollBackEntity reRollBackEntity) throws XbbException {
        try {
            saveRollBack(dataId, corpid, saasMark, businessType);

        } catch (Exception e) {
            LOG.error("abstractFormDataServiceImpl.afterSaveRollBack 回滚失败：", e);
        }

    }
}
